import { ResultEnum, RequestEnum } from '/@/enums/httpEnum';
import { Message } from '@arco-design/web-vue';
import { isNull, isUnDef, isEmpty, isString } from '/@/utils/is';
import type { AxiosTransform } from '/#/http';
import { getToken } from '/@/utils/auth';
import type { AxiosResponse } from 'axios';
import axios from 'axios';
import { checkStatus } from './checkStatus';
import { useUserStoreWithOut } from '/@/store/modules/user';

function joinTimestamp(join?: boolean, restful = false): string | object {
  if (!join) {
    return restful ? '' : {};
  }
  const now = new Date().getTime();
  if (restful) {
    return `?_t=${now}`;
  }
  return { _t: now };
}

export const transform: AxiosTransform = {
  /**
   * @description: 请求拦截器处理
   */
  requestInterceptors: (config, options) => {
    // 请求之前处理config
    const token = getToken();
    if (token && (config as Recordable)?.requestOptions?.withToken !== false) {
      // jwt token
      (config as Recordable).headers.Authorization = options.authenticationScheme
        ? `${options.authenticationScheme} ${token}`
        : token;
    }
    return config;
  },

  /**
   * @description: 响应拦截器处理
   */
  responseInterceptors: (res: AxiosResponse<any>) => {
    return res;
  },

  /**
   * @description: 响应错误处理
   */
  responseInterceptorsCatch: (axiosInstance: AxiosResponse, error: any) => {
    // const errorLogStore = useErrorLogStoreWithOut();
    // errorLogStore.addAjaxErrorInfo(error);
    const { response, code, message, config } = error || {};
    const errorMessageMode = config?.requestOptions?.errorMessageMode || 'none';
    const msg: string = response?.data?.error?.message ?? '';
    const err: string = error?.toString?.() ?? '';
    let errMessage = '';

    if (axios.isCancel(error)) {
      return Promise.reject(error);
    }

    try {
      if (code === 'ECONNABORTED' && message.indexOf('timeout') !== -1) {
        errMessage = '请求超时';
      }
      if (err?.includes('Network Error')) {
        errMessage = '网络繁忙';
      }

      if (errMessage) {
        if (errorMessageMode === 'message') {
          Message.error(errMessage);
        }
        return Promise.reject(error);
      }
    } catch (error) {
      throw new Error(error as unknown as string);
    }

    checkStatus(error?.response?.status, msg);

    // 添加自动重试机制 保险起见 只针对GET请求
    // const retryRequest = new AxiosRetry();
    // const { isOpenRetry } = config.requestOptions.retryRequest;
    // config.method?.toUpperCase() === RequestEnum.GET &&
    //   isOpenRetry &&
    //   // @ts-ignore
    //   retryRequest.retry(axiosInstance, error);
    return Promise.reject(error);
  },

  // 请求之前处理config
  beforeRequestHook(config, options) {
    const { joinTime } = options;
    const params = config.params || {};
    const data = config.data || false;
    // formatDate && data && !isString(data) && formatRequestDate(data);
    if (config.method?.toUpperCase() === RequestEnum.GET) {
      if (!isString(params)) {
        // 给 get 请求加上时间戳参数，避免从缓存中拿数据。
        config.params = Object.assign(params || {}, joinTimestamp(joinTime, false));
      } else {
        // 兼容restful风格
        config.url = config.url + params + `${joinTimestamp(joinTime, true)}`;
        config.params = undefined;
      }
    } else {
      if (!isString(params)) {
        // formatDate && formatRequestDate(params);
        if (
          Reflect.has(config, 'data') &&
          config.data &&
          (Object.keys(config.data).length > 0 || config.data instanceof FormData)
        ) {
          config.data = data;
          config.params = params;
        } else {
          // 非GET请求如果没有提供data，则将params视为data
          config.data = params;
          config.params = undefined;
        }
      } else {
        // 兼容restful风格
        config.url = config.url + params;
        config.params = undefined;
      }
    }
    return config;
  },
  /**
   * @description: 处理响应数据。如果数据不是预期格式，可直接抛出错误
   */
  transformResponseHook(res, options) {
    const { isReturnNativeResponse } = options;
    // 是否返回原生响应头 比如：需要获取响应头时使用该属性
    if (isReturnNativeResponse) {
      return res;
    }
    const { data } = res;

    if (!data) {
      // HTTP 请求没有返回值
      throw new Error('系统错误');
    }

    //  这里 code，data，message为 后台统一的字段，需要在 types.ts内修改为项目自己的接口返回格式
    const { code, data: result, message } = data;
    const hasSuccess = data && Reflect.has(data, 'code') && code === ResultEnum.SUCCESS;
    if (hasSuccess) {
      let successMsg = message;
      if (isNull(successMsg) || isUnDef(successMsg) || isEmpty(successMsg)) {
        successMsg = '操作成功';
      }
      if (options.successMessageMode === 'message') {
        Message.success(successMsg);
      }

      return result;
    } else {
      // 在此处根据自己项目的实际情况对不同的 code 执行不同的操作
      // 如果不希望中断当前请求，请 return 数据，否则直接抛出异常即可
      let timeoutMsg = '';
      switch (code) {
        case ResultEnum.TIMEOUT:
          timeoutMsg = '请求超时';
          // const userStore = useUserStoreWithOut();
          // userStore.setToken(undefined);
          // userStore.logout(true);
          break;
        case ResultEnum.UNAUTHoRIZED:
          timeoutMsg = '未登录';
          const userStore = useUserStoreWithOut();
          // userStore.setToken(undefined);
          // userStore.logout(true);
          userStore.goLogin();
          break;
        default:
          if (message) {
            timeoutMsg = message || '系统错误';
          }
      }
      Message.error(timeoutMsg);
      throw new Error(timeoutMsg);
    }
  },
};
